<?php

// 接口规约
abstract class ListSort {

    protected $query;

    public function __construct($query) {
        $this->query = $query;
    }

    abstract public function sort($list);
}

// 具体实现-示例
class ImplListSort extends ListSort {

    public function sort($list) {
        return $list;
    }
}

class ImplListSort2 extends ListSort {

    public function sort($list) {
        return array_reverse($list);
    }
}

// 业务排序
class BusinessListSort extends ListSort {
    public function sort($list) {
        return $list;
    }
}

// 推荐算法排序
class RecommendListSort extends ListSort {
    public function sort($list) {
        return $list;
    }
}

// 置顶排序
class TopListSort extends ListSort {
    public function sort($list) {
        return $list;
    }
}

// 测试
class ListSortReverse extends ListSort {
    public function sort($list) {
        return array_reverse($list);
    }
}

class ListSortShuffle extends ListSort {
    public function sort($list) {
        shuffle($list);
        return $list;
    }
}

class ListSortEngine {

    protected $list = array();
    protected $query = null;
    protected $plugins = array();

    public function __construct($list) {
        $this->list = $list;
    }

    public static function init($list) {
        return new self($list);
    }

    public function with($query) {
        $this->query = $query;
        return $this;
    }

    public function sortby($plugin) {
        $this->plugins[] = $plugin;
        return $this;
    }

    public function run() {
        $listTmp = $this->list;

        foreach ($this->plugins as $plugin) {
            $obj = new $plugin($this->query);
            $listTmp = $obj->sort($listTmp);    
        }

        return $listTmp;
    }
}

$list = array(array('id' => 1), array('id' => 2));
$query = array();

// 管理、插件、开闭原则、封装调用
// DSL：带查询参数初始化列表数据，然后分别根据x、y、z进行排序，最后执行返回结果
//
$newList = ListSortEngine::init($list)                  // 准备列表数据
    ->with($query)                                      // 指定上下文
    ->sortby('ImplListSort')->sortby('ImplListSort2')   // 装载排序插件
    ->run();                                            // 进行排序

var_dump($newList);

class ListSortEngineV2 {

    protected $query = null;
    protected $plugins = array();

    public static function context($query) {
        return new self($query);
    }

    protected function __construct($query) {
        $this->query = $query;
    }

    public function load($plugin) {
        $this->plugins[] = $plugin;
        return $this;
    }

    public function sort(&$list) {
        foreach ($this->plugins as $plugin) {
            $obj = new $plugin($this->query);
            $list = $obj->sort($list);    
        }

        return $list;
    }
}

$listData = $list;


// 1. 指定上下文
// 2. 装载排序插件
// 3. 进行排序
ListSortEngineV2::context($query)->load('ImplListSort')->load('ImplListSort2')->sort($list);

var_dump($list);

// 可测试性
// reverse 测试, shuffle 测试，总数不变（表面总数，实际总数，元素不重复） 
